/*-+-*****************************************************************************
 Copyright (C) 2009-2012 Oceanside Software Corporation (R)
 Dallas, Texas

 Author       : Jason T. Brower
 Purpose      : This file is part of a point-of-sale software package
                originally written for Table-Service Restaurants.
              
 Date         : July 8th of 2012
              
 History      : The application that this software file belongs to was 
                written over a 3-Year period.  The first version was written
                in C# .Net 3.5 using Windows Forms.  Being new to .Net at
                the time, I soon learned of Windows Presentation Foundation,
                liked the graphics capabilities and databinding so I
                migrated to WPF.  When the .Net 4.0 framework was released
                the application was migrated from 3.5 to 4.0. Now today,
                .Net 4.5 RC is out and I was already in process of migrating
                before I made this public.
                
Excuse Me     : Please excuse the coding style, it is not representative of
                my typical work.  During the three years I was under a very
                tight budget, constantly running out of funding and was 
                working 18 hour days hyped up on 5-Hour Energy.  The 
                design is not textbook.  It is monolythic because of
                previous issues I will not get into.  There are few comments
                in the code and the ones that are there may be incorrect.
                
What it is not: This is not the exact version that I took through PA-DSS 2.0
                nor is it the exact version running at my customer sites.
                I removed some details for security purposes including some
                encryption algorithms.  The reporting was removed because
                I was including a third party library that cannot be 
                published with this Open Source.
                
What it is    : This application has been running at high volume restaraunts
                for over a year.  It never freezes, crashes or does anything
                unexpected.  So long as it is built, installed and configured
                correctly, it is a strong system that we can all enhance.

Contact       : Please note that I can no longer work for free.  However, you
                can reach me at information@oceansidesw.com.                                                      

*********************************************************************************/
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using System.Xaml;
using System.Windows.Baml2006;
using System.Xml;
#if _LOCALDB
  using Oceanside.LocalDB;
#else
using Oceanside.RemoteDB;
#endif
namespace Oceanside
{
    public class App : System.Windows.Application
    {
        private static bool applicationIsRunningFull = false;
        public static bool ApplicationIsRunningFull
        {
            get { return App.applicationIsRunningFull; }
            set { App.applicationIsRunningFull = value; }
        }

        private static ResourceDictionary corporateResourceDictionary = null;
        public static ResourceDictionary CorporateResourceDictionary
        {
            get { return App.corporateResourceDictionary; }
            set { App.corporateResourceDictionary = value; }
        }

        public static CashMoneyBox CashMoneyWindowInstance = new CashMoneyBox();
        private static string processPathAndName;

        private static bool _hadUsbInitializationFailure = false;
        public static bool HadUsbInitializationFailure
        {
            get { return App._hadUsbInitializationFailure; }
            set { App._hadUsbInitializationFailure = value; }
        }

        private static bool _hadPaymentProcInitFailure = false;
        public static bool HadPaymentProcInitFailure
        {
            get { return App._hadPaymentProcInitFailure; }
            set { App._hadPaymentProcInitFailure = value; }
        }


        /// <summary>
        /// At one point I had the CEO of a major franchise call and wanted to learn about my system.
        /// I spent two days straight putting together a presentation to knock his socks off.  I made
        /// the application use this custom style file and styled the application to exactly match
        /// his corporate branding.  I will leave that story at that.  The style file depended upon
        /// using dynamic resources for binding.  It would take a little work to get going again, 
        /// but not too much.
        /// </summary>
        public static void LoadCorporateLook()
        {
            try
            {
                if (File.Exists("C:\\style.os"))
                {
                    Stream s = File.Open("C:\\style.os", FileMode.Open);

                    var reader = new Baml2006Reader(s);
                    var writer = new XamlObjectWriter(reader.SchemaContext);
                    while (reader.Read())
                    {
                        writer.WriteNode(reader);
                    }
                    CorporateResourceDictionary = writer.Result as ResourceDictionary;
                }
            }
            catch (Exception e)
            {
                Logging.LogException(e);
            }
        }


        /// <summary> 
        /// </summary>
        [STAThread()]
        [LoaderOptimization(LoaderOptimization.SingleDomain)]
        [HandleProcessCorruptedStateExceptionsAttribute]
        static void Main()
        {
            try
            {
                ///Make sure the logging directory exists.
                Logging.Init("KIOSK");

                try
                {
#if !_DEMO
                    Constants.GetSysConfigValues();
#endif
                }
                catch (Exception ex)
                {
                    Logging.LogException(ex);
                    System.Windows.MessageBox.Show("The oceanside.sys file could not be read properly, now exiting.");
                    Environment.Exit(0);
                }

                ///Load the corporate look and feel.
                if (Constants.IsCustomBrandedLicense)
                {
                    LoadCorporateLook();
                    Constants.LoadBrushes();
                }

                ///See if the MailMe Folder Exists.  If not, create it.
                try
                {
                    if (!Directory.Exists(Constants.CONST_MAILEME_FOLDER))
                    {
                        Directory.CreateDirectory(Constants.CONST_MAILEME_FOLDER);
                    }
                }
                catch (Exception ex)
                {
                    Logging.LogException(ex);
                }
#if !_DEBUG && ! _DEMO
                //Start the task manager as a hidden window to prevent the user from killing
                //applications and trying to reverse engineer the program.
                Process taskMan = new Process();
                taskMan.StartInfo.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.System);
                taskMan.StartInfo.FileName = "taskmgr.exe";
                taskMan.StartInfo.CreateNoWindow = true;
                taskMan.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                taskMan.Start();
#endif
                try
                {
                    Constants.ReadRegistryValues();
                }
                catch (Exception ex)
                {
                    Logging.LogException(ex);

                    System.Windows.MessageBox.Show("Could not read the proper registry values, now exiting.");
                    Environment.Exit(0);
                }


                ///Make sure the network is set to private or work.
                //PowerShell.SetNetwork();

                processPathAndName = Process.GetCurrentProcess().MainModule.FileName;

                ///Set this ASAP or get a null exception.
                Constants.MainDispatcher = Dispatcher.CurrentDispatcher;

                PosWindow.SwitchWindowDelegate_NOTHROW =
                    new PosWindow.SwitchWindowDelegateType(SwitchWindow_NOTHROW);

                Constants.InitIp();

                ///Main window
                PosWindow.MainPosWindow = Oceanside.MainWindow.Singleton;
                Constants.ErrorDispatcher = new UMD(Oceanside.MainWindow.ProgressCircle);

#if !_DEBUG
                PosWindow.MainPosWindow.Topmost = true;
#else
                PosWindow.MainPosWindow.Topmost = false;
#endif
                PosWindow.MainPosWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;

                PosWindow.MainPosWindow.WindowStyle = WindowStyle.None;
                PosWindow.MainPosWindow.ResizeMode = ResizeMode.NoResize;
                PosWindow.MainPosWindow.AllowsTransparency = false;
                PosWindow.MainPosWindow.ShowInTaskbar = false;
                PosWindow.MainPosWindow.Width = 1024;
                PosWindow.MainPosWindow.Height = 768;
                PosWindow.MainPosWindow.Show();

                ///Splash window
                Splasher.Splash = new SplashScreen();

#if !_DEBUG
                Splasher.Splash.Topmost = true;
#else
                Splasher.Splash.Topmost = false;
#endif
                Splasher.Splash.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                Splasher.Splash.WindowStyle = WindowStyle.None;
                Splasher.ShowSplash(Constants.CONST_TOTAL_INIT_STEPS);
                Splasher.Splash.Name = "Oceanside";
                Splasher.Splash.RegisterName(Splasher.Splash.Name, Splasher.Splash);
                Splasher.Splash.ShowInTaskbar = false;

                ///Init the application while the splash progress shows.
                Initialize();

                ///If we are running as administrator then the following line will set this application to run as real-time
                ///otherwise it will run as high.
                using (System.Diagnostics.Process p = System.Diagnostics.Process.GetCurrentProcess())
                {
                    p.PriorityClass = System.Diagnostics.ProcessPriorityClass.RealTime;
                }
                System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest;

                ///Mute the system so it does not beep when touching the screen.
#if !_LOCALDB                
                Oceanside.Sound.MuteSounds();
#endif

                App application = new App();

                application.DispatcherUnhandledException +=
                    new DispatcherUnhandledExceptionEventHandler(Current_DispatcherUnhandledException);

                application.Exit += new ExitEventHandler(application_Exit);
                application.SessionEnding +=
                    new SessionEndingCancelEventHandler(application_SessionEnding);
                AppDomain.CurrentDomain.UnhandledException +=
                    new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

                DispatcherTimer finalizerDispatchTimer = new DispatcherTimer();
                finalizerDispatchTimer.Interval = TimeSpan.FromSeconds(3);
                finalizerDispatchTimer.Tick += new EventHandler(finalizeStartup_Tick_NOTHROW);

                finalizerDispatchTimer.Start();

                ///Run the main message processing loop.
                application.Run(PosWindow.MainPosWindow);

            }
            catch (Exception e)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_APP_MAIN_UNCAUGHT_EXCEPTION, e);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void application_SessionEnding(object sender, SessionEndingCancelEventArgs e)
        {
            Environment.Exit(0);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void application_Exit(object sender, ExitEventArgs e)
        {

        }
        /// <summary>
        /// 
        /// </summary>
        public static void InvokeStopStoryBoard_NOTHROW()
        {
            try
            {
                if (Constants.MainDispatcher.CheckAccess())
                {
                    Oceanside.MainWindow.ProgressCircle.StopStoryboard_NOTHROW();
                }
                else
                {
                    Constants.MainDispatcher.BeginInvoke(new Action(InvokeStopStoryBoard_NOTHROW));
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_LVBBIND_INVOKE_STOP_STORYBOARD, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void InvokeStartStoryBoard_NOTHROW()
        {
            try
            {
                if (Constants.MainDispatcher.CheckAccess())
                {
                    Oceanside.MainWindow.ProgressCircle.StartStoryboard_NOTHROW();
                }
                else
                {
                    Constants.MainDispatcher.BeginInvoke(new Action(InvokeStartStoryBoard_NOTHROW));
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_PLACEHOLDER, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void finalizeStartup_Tick_NOTHROW(object sender, EventArgs e)
        {
            try
            {
                DispatcherTimer dp = (DispatcherTimer)sender;

                ///Kill the ticker.
                dp.Stop();

                if (HadUsbInitializationFailure)
                {
                    UMD.ShowGuiMessageSTASafe_NOTHROW("The system was unable to correctly initialize the USB subsystem.  This could cause magnetic strip readers, barcode scanners and other devices to malfunction.  This error has been reported and Oceanside Software Corporation will be investigating this issue.  You can restart the system in an attempt to resolve the issue.");
                }

                if (HadPaymentProcInitFailure)
                {
                    UMD.ShowGuiMessageSTASafe_NOTHROW("The system was unable to initialize the payment processor interface.  This will prevent your system from properly processing credit card, gift or loyalty transactions.");
                }

                using (DominicaEntities objectContext = new DominicaEntities(DominicaEntities.GetEfConString()))
                {
                    var q = from USER in objectContext.USERS
                            where USER.IsTerminated == false
                            select USER;

                    if (!q.Any())
                    {
                        Constants.ErrorDispatcher.Notify(Error.EType.E_NOUSERS, null);
                    }

                    var q1 = from SYSCONFIG in objectContext.SYSCONFIGS select SYSCONFIG;

                    if (!q1.Any())
                    {
                        Constants.ErrorDispatcher.Notify(Error.EType.E_NOSYSTEM_CONFIG, null);
                    }

                    var q2 = from MENU in objectContext.MENUS where MENU.IsDeleted == false select MENU;
                    if (!q2.Any())
                    {
                        Constants.ErrorDispatcher.Notify(Error.EType.E_NO_MENUS, null);
                    }

                    ///If the host name format is Ok, then check that there is actually a kiosk entry in the database
                    ///for this host name.
                    if (!KIOSK.VerifyHostNameFormat(KIOSK._cachedHostName))
                    {
                        Constants.ErrorDispatcher.Notify(Error.EType.E_INVALID_HOSTNAME_FORMAT, null);
                    }
                    else if (KIOSK.Get(SHIFT.GlobalContext) == null)
                    {
                        Constants.ErrorDispatcher.Notify(Error.EType.E_HOST_NOT_DEFINED, null);
                    }

                    if (null == DAYPART.GetDefaultDaypart(objectContext))
                    {
                        Constants.ErrorDispatcher.Notify(Error.EType.E_NODAYPART, null);
                    }

                    Task.Factory.StartNew(() => SystemMonitor.HealthMonitorTask(), TaskCreationOptions.LongRunning);

                    applicationIsRunningFull = true;
                }
            }
            catch (Exception excep)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_APP_FINALIZE_STARTUP, excep);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            try
            {
                Logging.LogMessage("Current_DispatcherUnhandledException in Main STA");
                Exception ex = (Exception)e.ExceptionObject;
                Logging.LogException(ex);
            }
            catch
            {
                ///The app is in big trouble at this point, nothing to do here.  We already tried to log
                ///and exception and that seems to have caused another exception.
            }
            finally
            {
                System.Diagnostics.ProcessStartInfo si = new System.Diagnostics.ProcessStartInfo();
                si.WorkingDirectory = Constants.RELAUNCH_DIRECTORY;
                si.FileName = Constants.RELAUNCH_DIR_AND_PROGRAM;
                System.Diagnostics.Process.Start(si);
                Process.GetCurrentProcess().Kill();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void Current_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            try
            {
                Logging.LogMessage("Current_DispatcherUnhandledException in Main STA");
                Logging.LogException(e.Exception);
            }
            finally
            {
                System.Diagnostics.ProcessStartInfo si = new System.Diagnostics.ProcessStartInfo();
                si.WorkingDirectory = Constants.RELAUNCH_DIRECTORY;
                si.FileName = Constants.RELAUNCH_DIR_AND_PROGRAM;
                System.Diagnostics.Process.Start(si);
                Environment.Exit(0);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        private static void ScreenSaverExceptionFunction_NOTHROW(Exception exc)
        {
            ///Notice that this is not wrapped in a try / catch even though this MUST not throw an
            ///exception.  That is because the function we are calling is exception safe.
            Constants.ErrorDispatcher.Notify(Error.EType.E_APP_SCREEN_SAVER_EXCEPTION, exc);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        [HandleProcessCorruptedStateExceptionsAttribute]
        private static void PeriodicTaskTimer_Tick_NOTHROW(object sender, EventArgs e)
        {
            try
            {
                ///Update all of the time labels.
                NotifyingDateAndTime.UpdateTimes();

                if (!ModalWindow.ModalDialogIsOpen && !Oceanside.MainWindow.ProgressCircle.IsRunning())
                {
                    ScreenSaverDelegates.CheckScreenSaverActivate();
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_APP_PERIODIC_TASK_TIMER_TICK, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private static void ExpireProgressBar()
        {
            for (int i = Splasher.CurrentStepValue; i < Constants.CONST_TOTAL_INIT_STEPS; i++)
            {
                Splasher.UpdateSplashStatus_NOTHROW("Finalizing...");
                System.Threading.Thread.Sleep(10);
            }
            Splasher.UpdateSplashStatus_NOTHROW("Copyright © 2009-2012 Oceanside Software Corporation ®");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        private static void Initialize()
        {
            Splasher.UpdateSplashStatus_NOTHROW("Searching for one of the Database Servers");

            bool connectionIsOpen = true;
            int retryCount = 0;

            do
            {
                try
                {
                    SHIFT.InitGlobalContext();
                    int dontCare = SHIFT.GlobalContext.MENUS.Count();
                    connectionIsOpen = true;
                }
                catch (Exception exc)
                {
                    connectionIsOpen = false;
                    retryCount++;
                    Splasher.UpdateSplashStatus_NOTHROW("Searching for a Database Server Retry #" + retryCount, true);
                    System.Threading.Thread.Sleep(3000);
                    Logging.LogException(exc);
                }
            } while (!connectionIsOpen);

            SHIFT.SetContextToNoTracking();

            ///Hide the mouse cursor if configured to do so.
            if (!Constants.ShowMouseCursor)
            {
                Mouse.OverrideCursor = Cursors.None;
            }

            Oceanside.SystemWindow.SwitchToPreviousScreenDelegate += new Action(LeaveSystemConfigDelegate_NOTHROW);


            if (KIOSK.CanLaunch())
            {
                ///Assure all of the functions are bound.
                Oceanside.Init.Assign();

                InitializeGlobals(SYSCONFIG.Get(SHIFT.GlobalContext));

                if (Constants.HasPaymentGateway)
                {
                    if (PROCESSOR.GetAll() != null)
                    {
                        Splasher.UpdateSplashStatus_NOTHROW("Initializing the Payment Processor API");
                        HadPaymentProcInitFailure = !Payments.PaymentEngine.InitializeAvailable();
                    }
                }

                TabControl tc = Oceanside.MainWindow.MainTabControl();

                if (Constants.IsQuickServiceMode)
                {
                    Oceanside.QuickOrderWindow.SetTabIndex(0);
                    Oceanside.QuickOrderWindow.AddInstanceToTabControl(ref tc);
                }
                else
                {
                    Oceanside.OrderWindow.SetTabIndex(0);
                    Oceanside.OrderWindow.AddInstanceToTabControl(ref tc);
                }

                Oceanside.ScreenSaver.SetTabIndex(1);
                Oceanside.ScreenSaver.AddInstanceToTabControl(ref tc);

                Oceanside.ControlPanelWindow.SetTabIndex(2);
                Oceanside.ControlPanelWindow.AddInstanceToTabControl(ref tc);

                Oceanside.SystemWindow.SetTabIndex(3);
                Oceanside.SystemWindow.AddInstanceToTabControl(ref tc);

                Oceanside.SplitWindow.SetTabIndex(4);
                Oceanside.SplitWindow.AddInstanceToTabControl(ref tc);

                Oceanside.CloseCheckWindow.SetTabIndex(5);
                Oceanside.CloseCheckWindow.AddInstanceToTabControl(ref tc);

                Oceanside.TimeSheetWindow.SetTabIndex(6);
                Oceanside.TimeSheetWindow.AddInstanceToTabControl(ref tc);

                Oceanside.FinancialWindow.SetTabIndex(7);
                Oceanside.FinancialWindow.AddInstanceToTabControl(ref tc);

                Oceanside.LoginWindow.SetTabIndex(8);
                Oceanside.LoginWindow.AddInstanceToTabControl(ref tc);

                Oceanside.ReportsWindow.SetTabIndex(9);
                Oceanside.ReportsWindow.AddInstanceToTabControl(ref tc);

                Oceanside.TransferTableWindow.SetTabIndex(10);
                Oceanside.TransferTableWindow.AddInstanceToTabControl(ref tc);

                Oceanside.CombineTablesWindow.SetTabIndex(11);
                Oceanside.CombineTablesWindow.AddInstanceToTabControl(ref tc);

                Oceanside.CheckHistoryWindow.SetTabIndex(12);
                Oceanside.CheckHistoryWindow.AddInstanceToTabControl(ref tc);

                Oceanside.SystemWindow.InitStatics();


                if (!Constants.IsQuickServiceMode)
                {
                    Oceanside.NewTableWindow.SetTabIndex(13);
                    Oceanside.NewTableWindow.AddInstanceToTabControl(ref tc);
                    NTBindings.Init();
                    NewTableWindow.PrepareForScreenChangeAction += new Action(NTBindings.PrepareForScreenChange_NOTHROW);
                }

                LIBindings.Init();
                LoginWindow.PrepareForScreenChangeAction
                    += new Action(LIBindings.PrepareForScreenChange_NOTHROW);

                ///Yes the screen saver also uses the login prep for screen change.
                ScreenSaver.PrepareForScreenChangeAction
                    += new Action(LIBindings.PrepareForScreenChange_NOTHROW);


                TransferTableBindings.Init();
                TransferTableWindow.PrepareForScreenChangeAction
                    += new Action(TransferTableBindings.PrepareForScreenChange_NOTHROW);


                TSBindings.Init();
                TimeSheetWindow.PrepareForScreenChangeAction
                    += new Action(TSBindings.PrepareForScreenChange_NOTHROW);

                CPBindings.Init();
                ControlPanelWindow.PrepareForScreenChangeAction
                    += new Action(CPBindings.PrepareForScreenChange_NOTHROW);

                ControlPanelWindow.PrepareForScreenLeaveAction
                    += new Action(CPBindings.PrepareForScreenLeave_NOTHROW);

                FinancialBindings.Init();
                FinancialWindow.PrepareForScreenChangeAction
                    += new Action(FinancialBindings.PrepareForScreenChange_NOTHROW);

                CCBindings.Init();
                CloseCheckWindow.PrepareForScreenChangeAction
                    += new Action(CCBindings.PrepareForScreenChange_NOTHROW);
                CloseCheckWindow.PrepareForScreenLeaveAction
                    += new Action(CCBindings.PrepareForScreenLeave_NOTHROW);

                POBindings.Init();
                if (!Constants.IsQuickServiceMode)
                {
                    OrderWindow.PrepareForScreenChangeAction
                        += new Action(POBindings.PrepareForScreenChange_NOTHROW);
                    OrderWindow.PrepareForScreenLeaveAction
                        += new Action(POBindings.PrepareForScreenLeave_NOTHROW);
                }
                else
                {
                    QuickOrderWindow.PrepareForScreenChangeAction
                        += new Action(POBindings.PrepareForScreenChange_NOTHROW);
                    QuickOrderWindow.PrepareForScreenLeaveAction
                        += new Action(POBindings.PrepareForScreenLeave_NOTHROW);
                }

                SplitBindings.Init();
                SplitWindow.PrepareForScreenChangeAction
                    += new Action(SplitBindings.PrepareForScreenChange_NOTHROW);

                SplitWindow.PrepareForScreenLeaveAction += 
                    new Action(SplitBindings.PrepareForScreenLeave_NOTHROW);

                CheckHistoryBindings.Init();
                CheckHistoryWindow.PrepareForScreenChangeAction
                    += new Action(CheckHistoryBindings.PrepareForScreenChange_NOTHROW);

                CombineTableBindings.Init();
                CombineTablesWindow.PrepareForScreenChangeAction
                    += new Action(CombineTableBindings.PrepareForScreenChange_NOTHROW);

#if !_DEBUG
                Splasher.UpdateSplashStatus_NOTHROW("Sending Log Status");
                Logging.DumpLogToFile();

#endif

                Splasher.UpdateSplashStatus_NOTHROW("Initializing Keyboard Paging");
                Oceanside.FullKeyboard.Init();

                Splasher.UpdateSplashStatus_NOTHROW("Initializing Notifications");
                //We need to register to listen to all of the inbound input from the keyboard so we can capture the magnetic strip data
                //that is sent via the PS2 port.  This particular event simply looks for the spaces.
                System.Windows.Input.InputManager.Current.PreNotifyInput +=
                    new NotifyInputEventHandler(ScreenSaverDelegates.PreNotifyInput_NOTHROW);

                ScreenSaver.ScreenSaverExceptionDelegate_NOTHROW +=
                    new ScreenSaver.ScreenSaverExceptionDelegateType(ScreenSaverExceptionFunction_NOTHROW);

                DispatcherTimer ScreenSaverAndTimeLabelTimer = new DispatcherTimer();
                ScreenSaverAndTimeLabelTimer.Interval = TimeSpan.FromSeconds(59);
                ScreenSaverAndTimeLabelTimer.Tick += new EventHandler(PeriodicTaskTimer_Tick_NOTHROW);
                ///Do not move this before when all of the window instances are initialized or the thread will crash.
                Splasher.UpdateSplashStatus_NOTHROW("Starting the Screen Saver Timer");
                PeriodicTaskTimer_Tick_NOTHROW(null, null); ///Call the timer once first to assure we notify of any pending errors asap.
                ScreenSaverAndTimeLabelTimer.Start();

                ///Collect the trash
                Splasher.UpdateSplashStatus_NOTHROW("Clean Memory Trail");
                System.GC.Collect(1, GCCollectionMode.Forced);
                System.GC.WaitForPendingFinalizers();


                LoginWindow.Show();

                ///Expire the progress bar.
                ExpireProgressBar();

                if (Constants.HasCfd)
                {
                    try
                    {
                        CFD.Init();
                    }
                    catch (Exception ex)
                    {
                        Logging.LogException(ex);
                    }
                }

                ///Start the animation that will fade out the splash screen.
                Splasher.StartFadeOut();
            }
            else
            {
                SHIFT.SetContextToAppendOnly();
                Splasher.UpdateSplashStatus_NOTHROW("Initializing Keyboard Paging");
                Oceanside.FullKeyboard.Init();

                Oceanside.SystemWindow.IsConfigOnlyMode = true;
                Oceanside.SystemWindow.InitStatics();

                TabControl tc = Oceanside.MainWindow.MainTabControl();
                Oceanside.SystemWindow.AddInstanceToTabControl(ref tc);

                Constants.HasPaymentGateway = false;

                SystemWindow.Show();

                ///Expire the progress bar.
                ExpireProgressBar();

                ///Start the animation that will fade out the splash screen.
                Splasher.StartFadeOut();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sysConfig"></param>
        private static void InitializeGlobals(SYSCONFIG sysConfig)
        {
            ///Now convert to milliseconds
            if (sysConfig != null)
            {
                Constants.ScreenSaverTimeout_MS = sysConfig.ScreenLockTimeout > 60 ? sysConfig.ScreenLockTimeout : 60;
                Constants.ScreenSaverTimeout_MS = Constants.ScreenSaverTimeout_MS * 1000;

                Constants.PrintQueueTimeout_MS = sysConfig.PrintQueueTimeout * 1000;

                Constants.ForceOrderOnScreenSaverTimeout = sysConfig.ForceOrderOnScreenTimeout;

                ///A login token is basically used to enable the magstripe login cards.
                Constants.MagCardLoginToken = sysConfig.UserMagSwipeToken;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private static void LeaveSystemConfigDelegate_NOTHROW()
        {
            try
            {
                Oceanside.ControlPanelWindow.Show();
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_APP_EXIT_SYSTEM_WINDOW, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param Name="window"></param>
        public static void SwitchWindow_NOTHROW(PosWindow forwardWindow)
        {
            try
            {
                ///Tab pages will not switch if a window is open modal
                if (!ModalWindow.ModalDialogIsOpen)
                {
                    if (PosWindow.ActiveWindowInstance is SystemWindow)
                    {
                        LeaveSystemWindowTask_NOTHROW(forwardWindow);
                    }
                    else
                    {
                        SwitchWindowWithLock_NOTHROW(forwardWindow);
                    }
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_APP_SWITCH_TO_WINDOW, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="window"></param>
        private static void SwitchWindowWithLock_NOTHROW(object obj)
        {
            try
            {
                PosWindow window = (PosWindow)obj;
                lock (PosWindow.ScreenSwitchLock)
                {
                    if (PosWindow.ActiveWindowInstance != null && (window != PosWindow.ActiveWindowInstance))
                    {
                        PosWindow.ActiveWindowInstance.PrepareForScreenLeave();
                    }

                    if ((window is LoginWindow || window is ScreenSaver) && App.ApplicationIsRunningFull && SHIFT.GlobalContext != null)
                    {
                        if (SHIFT.Current != null)
                        {
                            SHIFT.Current.IsLocked = false;
                        }
                        SHIFT.GlobalContext.SaveChanges();
                    }
                    window.PrepareForScreenChange();
                    TabControl tc = Oceanside.MainWindow.MainTabControl();
                    tc.SelectedIndex = window.MyTabIndex;
                    PosWindow.PreviousWindowInstance = PosWindow.ActiveWindowInstance;
                    PosWindow.ActiveWindowInstance = window;
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_APP_SWITCH_TO_WINDOW_WITH_LOCK, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void LeaveSystemWindowTask_NOTHROW(PosWindow window)
        {
            try
            {
                Oceanside.SystemWindow.Cancel_NOTHROW();
                SwitchWindowWithLock_NOTHROW(window);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_APP_EXIT_SYSTEM_CONFIG_WINDOW_TASK, exc);
            }
        }
    }
}
